#
# Created: 2025-07-27
import plotly.graph_objects as go  # 导入绘图工具包
import plotly.express as px  # 导入绘图工具包
import numpy as np  # 导入数值计算工具包
import pandas as pd  # 导入数据处理工具包
from sklearn.linear_model import LogisticRegression  # 导入逻辑回归模型
from sklearn.metrics import roc_curve, roc_auc_score

# 导入ROC曲线相关的评估指标

np.random.seed(0)  # 固定随机种子，以便结果可复现

# 人为地添加噪音，使任务更加困难
df = px.data.iris()  # 加载鸢尾花数据集
samples = df.species.sample(n=50, random_state=0)
# 从'species'列中随机抽取50个样本
np.random.shuffle(samples.values)  # 打乱样本的顺序
df.loc[samples.index, 'species'] = samples.values
# 将打乱后的样本顺序赋值给数据集

# 定义输入和输出
X = df.drop(columns=['species', 'species_id'])  # 提取特征
y = df['species']  # 提取目标变量

# 拟合模型
model = LogisticRegression(max_iter=200)  # 创建逻辑回归模型
model.fit(X, y)  # 对模型进行训练
y_scores = model.predict_proba(X)  # 预测概率

# 对标签进行独热编码以便绘图
y_onehot = pd.get_dummies(y, columns=model.classes_)

# 创建一个空的图形，并在每次计算新类别时添加新线
fig = go.Figure()  # 创建一个绘图对象
fig.add_shape(type='line', line=dict(dash='dash'),
              x0=0, x1=1, y0=0, y1=1)

for i in range(y_scores.shape[1]):
    y_true = y_onehot.iloc[:, i]
    y_score = y_scores[:, i]

    fpr, tpr, _ = roc_curve(y_true, y_score)  # 计算ROC曲线的假阳率和真阳率
    auc_score = roc_auc_score(y_true, y_score)  # 计算AUC值

    name = f"{y_onehot.columns[i]} (AUC={auc_score:.2f})"
    fig.add_trace(go.Scatter(x=fpr, y=tpr, name=name,
                             mode='lines'))  # 绘制ROC曲线

fig.update_layout(
    xaxis_title='False Positive Rate',  # 设置X轴标题
    yaxis_title='True Positive Rate',  # 设置Y轴标题
    yaxis=dict(scaleanchor="x", scaleratio=1),  # 设置Y轴与X轴的比例相同
    xaxis=dict(constrain='domain'),  # 约束X轴范围在0到1之间
    width=500, height=500,  # 设置图形的宽度和高度
    # legend=dict(x=0.5,y=0.1,bgcolor='rgba(255,255,255,0.5)')
    # 将图例移动到图的内部，并设置背景色为半透明白色
)
fig.show()
